/*
 * lab3chq21.c
 *
 *  Created on: Mar 6th, 2011
 *      Author: stellarhopper
 */

/*
 * PROGRAM DESCRIPTION
 *
 * Demonstrate PCA capabilities.
 *
 */

/*
 * COMPILER FLAGS
 * sdcc -c --debug -mmcs51 --std-sdcc99 --model-large
 *
 * LINKER FLAGS
 * sdcc --debug -mmcs51 --code-loc 0x0000 --code-size 0x8000 --xram-loc 0x0000 --xram-size 0x8000 --model-large --out-fmt-ihx
 *
 * USAGE SPECIFICATIONS:
 * Baud rate - 57600
 */

//Function Header
/*
* NAME :
*
* DESCRIPTION :
*
* INPUTS :
*       PARAMETERS:
*		GLOBALS:
*
* OUTPUTS :
*       GLOBALS:
*       RETURN:
*
* PROCESS :
*                   [1]
*
* NOTES :
*/

/*==============================================INCLUDES=========================================*/
#include <at89c51ed2.h>  //also includes 8052.h and 8051.h
#include <mcs51reg.h>
#include <stdio.h>
#include <stdlib.h>

/*==============================================DEFINES==========================================*/
#define TRUE 1
#define FALSE 0
#define ON 1
#define OFF 0
#define PB_SWITCH P1_5


/*==============================================GLOBALS==========================================*/

enum RETCODE{							//retcodes/parameter flags for all functions
	OK = 0
};

/*=========================================FUNCTION PROTOTYPES===================================*/

void putchar (char c);
char getchar (void);
int putstr (char *s);
int getstr (char *s);
void serialInit(int);
void clearScr(void);
void myDelay(int j);
void initAll(void);

void printMenu(void);
void pbDebounce(void);

/*=========================================FUNCTION DEFINITIONS===================================*/

/*
* NAME :            _sdcc_external_startup
*
* DESCRIPTION :     Will run before main(). Used to initialize registers etc. as required
*
* INPUTS :
*       PARAMETERS:	-
*		GLOBALS:	AUXR
*
* OUTPUTS :
*       GLOBALS:	AUXR
*       RETURN:		-
*
*/

_sdcc_external_startup() {

	AUXR |= 0x0C;
	return 0;
}

/*
* NAME :            putchar
*
* DESCRIPTION :     print 1 character to serial port
*
* INPUTS :
*       PARAMETERS:	char c
*		GLOBALS:	SCON
*
* OUTPUTS :
*       GLOBALS :	SBUF, TI
*       RETURN :	-
*
* PROCESS :
*                   [1]	Wait for port to be ready
* 					[2]	Print char and clear TI
*/

void putchar (char c) {

	while ((SCON & 0x02) == 0);    				// wait for TX ready, spin on TI
	SBUF = c;  									// load serial port with transmit value
	TI = 0;  									// clear TI flag
}

/*
* NAME :            getchar
*
* DESCRIPTION :     get 1 character from serial port
*
* INPUTS :
*       PARAMETERS:	-
*		GLOBALS:	SCON
*
* OUTPUTS :
*       GLOBALS :	SBUF, RI
*       RETURN :	SBUF - character received
*
* PROCESS :
*                   [1]	Wait for character to be received
* 					[2]	Clear RI
*					[3] Return character
*/

char getchar () {

    while ((SCON & 0x01) == 0);  				// wait for character to be received, spin on RI
	RI = 0;										// clear RI flag
	return SBUF;  								// return character from SBUF
}

/*
* NAME :            putstr
*
* DESCRIPTION :     Print a string to serial port
*
* INPUTS :
*       PARAMETERS:	char *s
*		GLOBALS:	-
*
* OUTPUTS :
*       GLOBALS :	-
*       RETURN :	Number of characters transmitted
*
* PROCESS :
*                   [1]  Transmit characters till oxoo (NULL) is encountered
*/

int putstr (char *s) {

	int i = 0;
	while (*s){									// output characters until NULL found
		putchar(*s++);
		i++;
	}
	//putchar('\n\r');
	return i+1;
}

/*
* NAME :            getstr
*
* DESCRIPTION :     Get a string from serial port
*
* INPUTS :
*       PARAMETERS:	char *s
*		GLOBALS:	-
*
* OUTPUTS :
*		PARAMETERS: char *s
*       GLOBALS :	-
*       RETURN :	i - number of characters read
*
* PROCESS :
*                   [1]  Accept characters till 0x0D encountered (CR)
*					[2]	 Store starting at given location (*s)
*
* NOTES :           Is not safe from buffer overrun. Assumes valid memory available for all characters input.
*					Can be substituted with gets() which is equally unsafe but I wrote this so am going with it :)
*/

int getstr (char *s) {

	int i = 0;
	do {
		s[i] = getchar();
		putchar(s[i]);
		i++;
	} while(s[i-1] != 0x0D);  					//0x0D is <CR>
	s[i-1] = 0x00;								//replace <CR> with NULL (0x00)
	putchar('\n\r');
	return (i-1);
}

/*
* NAME :            serialInit
*
* DESCRIPTION :     Initialize the serial port
*
* INPUTS :
*       PARAMETERS:	int br (BAUD RATE)
*		GLOBALS:	-
*
* OUTPUTS :
*       GLOBALS :	PCON, SCON, TMOD, TH1, TR1, TI
*       RETURN :	-
*
*
* NOTES :  Baud rate is supplied as 0xFF for 56700 etc
*/

void serialInit(int br) {

/*
	PCON |= 0x80;								//SMOD1 = 1
	SCON = 0x50;								//uart in mode 1 (8 bit), REN=1
	BDRCON &=0xEC;								//BRR=0; SRC=0;
	BDRCON |=0x0E;								//TBCK=1;RBCK=1; SPD=1
	BRL = br;
	BRL=0xFD;									//115200 Bds at 11.059MHz
	EA = 1;										//Enable serial interrupt
	BDRCON |= 0x10;								//Baud rate generator run
*/


	PCON |= 0x80;								//configure uart, fast baud
	SCON = 0x50;                   			 	//SCON: mode 1, 8-bit UART, enable rcvr
	TMOD |= 0x20;                   			//TMOD: timer 1, mode 2, 8-bit reload for serial
	TMOD |= 0x01;                   			//TMOD: timer 1, mode 2, 8-bit reload for debounce
	TH1 = br;                   				//TH1:  reload value for baudrate
	TR1   = 1;                      			//TR1:  timer 1 run
	TI    = 1;                      			//TI:   set TI to send first char of UART
}

/*
* NAME :            initAll
*
* DESCRIPTION :     Reset global variables to initial values
*
* INPUTS :
*       PARAMETERS:	-
*		GLOBALS:	-
*
* OUTPUTS :
*       GLOBALS :	-
*       RETURN :	-
*/

void initAll() {

	int i = 0;

	EA = 1;
	PB_SWITCH = 1;
}

/*
* NAME :            clearScr
*
* DESCRIPTION :     Clears and resets the VT100 terminal
*
* INPUTS :
*       PARAMETERS:	-
*		GLOBALS:	-
*
* OUTPUTS :
*       GLOBALS :	-
*       RETURN :	-
*
*
* NOTES :           Will clear the VT100 terminal by sending control sequences to reset and clear entire screen
*					Reset: ESC c
*					Clear Screen: ESC [ 2 J
*/

void clearScr() {
	printf("\033c");			//reset terminal
	printf("\033[2J");			//clear screen
}

/*
* NAME :            myDelay
*
* DESCRIPTION :     Provide a delay
*
* INPUTS :
*       PARAMETERS:	int j - empirical - j=1 ~ 1 second
*		GLOBALS:	-
*
* OUTPUTS :
*       GLOBALS :	-
*       RETURN :	-
*/

void myDelay(int j) {
	int i = 0;
	int cnt = 0;

	j*=100;
	while(j) {
		for(i=0; i<100; i++);
		for(i=0; i<100; i++);
		for(i=0; i<100; i++);
		for(i=0; i<100; i++);
		for(i=0; i<100; i++);
		for(i=0; i<100; i++);
		for(i=0; i<100; i++);
		for(i=0; i<100; i++);
		for(i=0; i<100; i++);
		for(i=0; i<100; i++);
		j--;
	}

}

/*
* NAME :            printMenu
*
* DESCRIPTION :     print menu
*
* INPUTS :
*       PARAMETERS:	
*		GLOBALS:	
*
* OUTPUTS :
*		PARAMETERS: 
*       GLOBALS :	
*       RETURN :	
*
* PROCESS :
*                   [1]  
*
* NOTES :           
*/


void printMenu() {
	clearScr();
	putstr("***********************************WELCOME**********************************\n\r");
	putstr("*                                                                          *\n\r");
	putstr("*  This program will provide demonstrate PCA capabilities                  *\n\r");
	putstr("*                                                                          *\n\r");
	putstr("****************************************************************************\n\n\n\r");

	putstr("1-> Watchdog Test \n\r");
	putstr("2-> Capture Mode (negative edge) \n\r");
	putstr("3-> Capture Mode (positive edge) \n\r");
	putstr("4-> Capture Mode (both edges) \n\r");
	putstr("5-> Compare mode \n\r");
	putstr("6-> High Speed Output \n\r");
	putstr("\n\r");
	putstr("****************************************************************************\n\r\n\r");
	putstr("Command > ");
}


/*=========================================FUNCTION MAIN==========================================*/


void main() {

	char cmd = 0;

	serialInit(0xFF); 						//0xFF gives Baud Rate 57600
	initAll();
	clearScr();
	P1_7 = OFF;

	while(1){
		printMenu();
		cmd = getchar();
		putchar(cmd);

		switch (cmd) {
			case '1': 						//wdt
				clearScr();
				putstr("This will demonstrate the watchdog timer\n\r");
				putstr("Will enter infinite loop on key press and will be reset by WDT...\n\r");
				getchar();

				CCAPM4 = 0x48;
				CCAP4L = 0xFF;
				CCAP4H = 0xFF;
				CMOD = 0x40; 				//Set WDTE to enable watchdog
				CR = 1;

				while(1);					//Infinite loop, will be broken by WDT
				break;

			case '2': 						//-ve trigger capture
				clearScr();
				CH = 0;
				CL = 0;
				CMOD = 0x01;  				//enable PCA interrupts
				CCF2 = 0;					//clear CCF2 (in CCON) then wait in it till PCA timer sets it
				CCAPM2 = 0x10;				//16bit capture, negative trigger (0x20 for +ve edge, 0x30 for both)
				CCAP2L = 0;
				CCAP2H = 0;
				putstr("Starting Capture mode on negative edge.\n\r");
				putstr("Press PushButton SW3 to capture\n\r");

				CR = 1;						//run PCA timer (in CCON)

				while (CCF2 == 0);
				CCF2 = 0;

				printf("Captured value: 0x%02X 0x%02X\n\r", CCAP2H, CCAP2L);
				putstr("Press any key to continue: \n\r");
				getchar();

				CCAP2L = 0;
				CCAP2H = 0;
				CR = 0;
				break;

			case '3': 						//+ve trigger capture
				clearScr();
				CH = 0;
				CL = 0;
				CMOD = 0x01;  				//enable PCA interrupts
				CCF2 = 0;					//clear CCF2 (in CCON) then wait in it till PCA timer sets it
				CCAPM2 = 0x20;				//16bit capture, positive trigger
				CCAP2L = 0;
				CCAP2H = 0;
				putstr("Starting Capture mode on positive edge.\n\r");
				putstr("Press PushButton SW3 to capture\n\r");

				CR = 1;						//run PCA timer (in CCON)

				while (CCF2 == 0);
				CCF2 = 0;

				printf("Captured value: 0x%02X 0x%02X\n\r", CCAP2H, CCAP2L);
				putstr("Press any key to continue: \n\r");
				getchar();

				CR = 0;
				CCAP2L = 0;
				CCAP2H = 0;
				break;

			case '4': 						//both trigger capture
				clearScr();
				clearScr();
				CH = 0;
				CL = 0;
				CMOD = 0x01;  				//enable PCA interrupts
				CCF2 = 0;					//clear CCF2 (in CCON) then wait in it till PCA timer sets it
				CCAPM2 = 0x30;				//16bit capture, both trigger
				CCAP2L = 0;
				CCAP2H = 0;
				putstr("Starting Capture mode on both edges.\n\r");
				putstr("Press PushButton SW3 to capture\n\r");

				CR = 1;						//run PCA timer (in CCON)

				while (CCF2 == 0);
				CCF2 = 0;

				printf("Captured value for button press: 0x%02X 0x%02X\n\r", CCAP2H, CCAP2L);

				while (CCF2 == 0);
				CCF2 = 0;

				printf("Captured value for button release: 0x%02X 0x%02X\n\r", CCAP2H, CCAP2L);
				putstr("Press any key to continue: \n\r");
				getchar();

				CR = 0;
				CCAP2L = 0;
				CCAP2H = 0;
				break;

			case '5':  //compare
				clearScr();
				putstr("This will demonstrate compare mode\n\r");
				putstr("Will set CCF2 when CL and CH equal CCAPL and CCAPH \n\r");
				putstr("Compare value is set to 0x7FFF. \n\r");
				putstr("LED will turn on on a successful compare\n\r");

				CMOD = 0x01; 				//enable PCA interrupts
				CCF2 = 0;					//clear CCF2 (in CCON) then wait in it till PCA timer sets it
				CH = 0;
				CL = 0;
				CCAPM2 = 0x48;
				CCAP2L = 0xFF;
				CCAP2H = 0x7F;

				CR = 1;						//run PCA timer (in CCON)
				while (CCF2 == 0) {
					//CH = 0;
					//CL = 0;
				}
				CCF2 = 0;
				P1_7 = ON; 					//LED ON

				putstr("Press any key to continue: \n\r");
				getchar();

				P1_7 = OFF;
				CR = 0;
				break;

			case '6': //HSO
				clearScr();
				putstr("This will demonstrate High Speed Output mode\n\r");
				putstr("P1.5 will toggle each time comparison between PCA counter and CCAP registers is true \n\r");
				putstr("LED will be ON while in HSO mode\n\r");

				CMOD = 0x01; 				//enable PCA interrupts
				CCF2 = 0;					//clear CCF2 (in CCON) then wait in it till PCA timer sets it
				CH = 0;
				CL = 0;
				CCAP2L = 0xFF;
				CCAP2H = 0x7F;
				CCAPM2 = 0x4C;

				CR = 1;						//run PCA timer (in CCON)
				while (CCF2 == 0) {
					//CH = 0;
					//CL = 0;
				}
				CCF2 = 0;
				P1_7 = ON;

				putstr("Press any key to continue: \n\r");
				getchar();

				P1_7 = OFF;
				CR = 0;
				break;

			default:
				clearScr();
				putstr("Invalid Entry, Try again! \n\r");
				myDelay(1);
		}
	}
}

